package emulator.assembler;

import java.util.HashSet;
import java.util.LinkedList;

public class CodeAnalyzer {
	private Assembler assembler;
	private DataDescriptionTable data_table;
	private byte[] memory;
	private LinkedList<Integer> address_list;
	private HashSet<Integer> visited_addresses;
	
	public CodeAnalyzer(Assembler assembler,
						DataDescriptionTable data_table,
						byte[] memory,
						LinkedList<Integer> address_list)
	{
		this.assembler = assembler;
		this.data_table = data_table;
		this.memory = memory;
		this.address_list = address_list;
		visited_addresses = new HashSet<Integer>();
	}
	
	public void runAnalysis()
	{
		while (address_list.size() > 0)
		{
			int address = address_list.pop();
			if (!visited_addresses.contains(address))
			{
				// analyze code thread
				try {
					while (address < memory.length)
					{
						visited_addresses.add(address);
						Instruction instruction = assembler.getInstruction(memory, address);
						registerInstruction(address, instruction);
						if (instruction.isEnd())
							break;
						address += instruction.getByteCount();
					}
				}
				catch (Exception e)
				{ 
					e.getMessage();
				}
				// collect new jump targets
				for (Integer target : assembler.getSymbols().getJumpTargets())
				{
					if (!visited_addresses.contains(target))
						address_list.push(target);
				}
			}
		}
		data_table.reindex();
	}

	private void registerInstruction(int address, Instruction instruction) {
		data_table.insertInstruction(address, instruction);
	}
}
